package engine.gameObject;

import engine.collider.BoundingVolume;
import engine.collider.ContactPoint;
import engine.collider.bounds.BoundingElement;
import engine.collider.bounds.BoundingSphere;
import engine.scene.Scene;
import engine.scene.tree.Octree;

import static org.lwjgl.opengl.GL11.*;

/**
 * Represents the standard 3d object. 
 * 
 * @author Richard
 *
 */
public abstract class GameObject {

	private double[] position;
	private double[] rotation;
	private double[] scale;
	
	private boolean inNearPane = true;
	private boolean markAsLarge;
	
	private BoundingVolume boundingVolume;
	
	private BoundingSphere boundingSphere;
	
	private Octree currentOctree;
	private Scene scene;
	
	private boolean rendered;

	public GameObject() {
		position = new double[]{0, 0, 0};
		rotation = new double[]{0, 0, 0};
		scale = new double[]{1, 1, 1};
		
		boundingSphere = new BoundingSphere();
		boundingVolume = new BoundingVolume();
	}
	
	public boolean isInNearPane() {
		return inNearPane;
	}

	public void setInNearPane(boolean inNearPane) {
		this.inNearPane = inNearPane;
	}
	
	public void renderAbs(float timeElapsed) {
		if(rendered) {
			return;
		}
		
		glPushMatrix(); 
		{
			glTranslated(position[0], position[1], position[2]);
			
			render(timeElapsed);
		}
		glPopMatrix();
		
		rendered = true;
	}
	
//	public void lateUpdateAbs(float timeElapsed) {
//		lateUpdate(timeElapsed);
//	}
	
//	public void lateUpdate(float timeElapsed) {}
	
	public void render(float timeElapsed) {}

	public double[] getPosition() {
		return position;
	}
	
	public double getPosX() {
		return position[0];
	}
	
	public double getPosY() {
		return position[1];
	}
	
	public double getPosZ() {
		return position[2];
	}

	public void setPosition(double[] position) {
		setPosition(position[0], position[1], position[2]);
	}
	
	public void setPosition(double x, double y, double z) {
		position[0] = x;
		position[1] = y;
		position[2] = z;
	}

	public double[] getRotation() {
		return rotation;
	}

	public void setRotation(double[] rotation) {
		this.rotation = rotation;
	}
	
	public void setRotation(double rotX, double rotY, double rotZ) {
		rotation[0] = rotX;
		rotation[1] = rotY;
		rotation[2] = rotZ;
	}

	public double[] getScale() {
		return scale;
	}

	public void setScale(double[] scale) {
		this.scale = scale;
	}
	
	public void setScale(double x, double y, double z) {
		scale[0] = x;
		scale[1] = y;
		scale[2] = z;
	}
	
	public boolean isCollidable() {
		return boundingVolume.getBoundingElements().size() > 0;
	}
	
//	public void setBoundingVolume(BoundingVolume boundingVolume) {
//		if(this.boundingVolume == null) {
//			//TODO if colliding trees are already initialized, this object needs to be inserted into the tree
//		}
//		
//		this.boundingVolume = boundingVolume;
//	}
	
	public void addBoundingElement(BoundingElement boundingElement) {
		boundingVolume.getBoundingElements().add(boundingElement);
	}
	
	public BoundingVolume getBoundingVolume() {
		return boundingVolume;
	}

	public void setBounds(double x, double y, double z, double radius) {
		boundingSphere.setPosition(x, y, z);
		boundingSphere.setRadius(radius);
	}
	
	public BoundingSphere getBoundingSphere() {
		return boundingSphere;
	}
	
	public void setCurrentOctree(Octree currentOctree) {
		this.currentOctree = currentOctree;
	}
	
	public Octree getCurrentOctree() {
		return currentOctree;
	}
	
	public void setRendered(boolean rendered) {
		this.rendered = rendered;
	}
	
	public void collided(ContactPoint contactPoint, double timeLeft) {
		
	}

	public Scene getScene() {
		return scene;
	}

	public void setScene(Scene scene) {
		this.scene = scene;
	}

	public boolean isMarkAsLarge() {
		return markAsLarge;
	}

	public void setMarkAsLarge(boolean markAsLarge) {
		this.markAsLarge = markAsLarge;
	}
}
